/**
  ******************************************************************************
  * @file    libusb_adb.h
  * @author  Newtons_Prism
  * @version V1.0.0
  * @date    19-April-2022
  * @brief   USB ADB Library
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2022 Newtons_Prism</center></h2>
  *
  * Licensed under GNU General Public License v3.0, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        https://www.gnu.org/licenses/gpl-3.0
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

#ifndef LIBUSB_ADB_H
#define LIBUSB_ADB_H

#define _CRT_SECURE_NO_WARNINGS //޹ؾ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libusb.h"

#define MAX_PAYLOAD 255

#define A_SYNC 0x434e5953
#define A_CNXN 0x4e584e43
#define A_OPEN 0x4e45504f
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
#define A_AUTH 0x48545541

#define A_VERSION 0x01

#define ADB_AUTH_RSAPUBLICKEY  0x03

#define ADB_CLASS              0xff
#define ADB_SUBCLASS           0x42
#define ADB_PROTOCOL           0x01

static const char* AUTH_KEY = "ADB AUTH RSAPUBLICKEY";
static const char* TOUCH_CMD = "shell:while (true); do r=`logcat -t 1 | grep input`;  if [ $? -eq 0 ]; then echo $r; logcat -c; ${r#*@}; fi; done &";
//static const char* TOUCH_CMD = "while [[ true ]];do r=`logcat -t 1 | grep -E 'input|Killing'`;if [[ $? -eq 0 ]];then if [[ $r == *'screenprojection'* ]];then exit;fi;if [[ $r == *'@input'* ]];then ${r#*@};fi;logcat -c;fi;done &";



typedef struct amessage amessage;
typedef struct apacket apacket;
typedef struct adb_handle adb_handle;
typedef enum state state;

enum state {
	INIT = 0,
	INIT_DONE,
	SEND_AUTH,
	SEND_CMD,
	IDLE,
};

struct amessage {
	uint32_t command;
	uint32_t arg0;
	uint32_t arg1;
	uint32_t data_length;
	uint32_t data_check;
	uint32_t magic;
};

struct apacket {
	amessage msg;
	uint8_t data[MAX_PAYLOAD];
};

struct adb_handle {
	libusb_device_handle* dev_handle;
	uint8_t				  adb_read_pipe;
	uint8_t				  adb_write_pipe;
	uint16_t			  zero_mask;
	state				  state;
};


apacket* get_apacket(void);

void put_apacket(apacket* p);

int usb_read(adb_handle* handle, void* data, int len);

int check_header(apacket* p);

int check_data(apacket* p);

int remote_read(adb_handle* handle, apacket* p);

int usb_write(adb_handle* handle, const void* data, int len);

int remote_write(adb_handle* handle, apacket* p);

void send_packet_remote(adb_handle* handle, apacket* p);

int send_auth_remote(adb_handle* handle, const char* key);

int send_cmd_remote(adb_handle* handle, const char* cmd);

int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol);

int match_with_endpoint(adb_handle* handle, const struct libusb_interface_descriptor* interface);

void match_with_interface(adb_handle* handle);


#endif
